package im.actor.runtime.js.webrtc; import com.google.gwt.core.client.JavaScriptException; import com.google.gwt.core.client.JavaScriptObject; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import im.actor.runtime.function.CountedReference; import im.actor.runtime.js.entity.JsClosure; import im.actor.runtime.js.entity.JsClosureError; import im.actor.runtime.js.webrtc.js.JsMediaStream; import im.actor.runtime.js.webrtc.js.JsPeerConnection; import im.actor.runtime.js.webrtc.js.JsPeerConnectionListener; import im.actor.runtime.js.webrtc.js.JsRTCIceCandidate; import im.actor.runtime.js.webrtc.js.JsSessionDescription; import im.actor.runtime.js.webrtc.js.JsSessionDescriptionCallback; import im.actor.runtime.promise.Promise; import im.actor.runtime.promise.PromiseFunc; import im.actor.runtime.promise.PromiseResolver; import im.actor.runtime.webrtc.WebRTCMediaStream; import im.actor.runtime.webrtc.WebRTCPeerConnection; import im.actor.runtime.webrtc.WebRTCPeerConnectionCallback; import im.actor.runtime.webrtc.WebRTCSessionDescription; public class PeerConnection implements WebRTCPeerConnection { private JsPeerConnection peerConnection; private ArrayList<WebRTCPeerConnectionCallback> callbacks = new ArrayList<>(); private HashMap<JsMediaStream, MediaStream> streams = new HashMap<>(); public PeerConnection(JsPeerConnection peerConnection) { this.peerConnection = peerConnection; this.peerConnection.setListener(new JsPeerConnectionListener() { @Override public void onIceCandidate(JsRTCIceCandidate candidate) { for (WebRTCPeerConnectionCallback c : callbacks) { c.onCandidate(candidate.getLabel(), candidate.getId(), candidate.getSDP()); } } @Override public void onStreamAdded(JsMediaStream stream) { MediaStream stream1 = new MediaStream(stream); streams.put(stream, stream1); for (WebRTCPeerConnectionCallback c : callbacks) { c.onStreamAdded(stream1); } } @Override public void onStreamRemoved(JsMediaStream stream) { MediaStream stream1 = streams.get(stream); if (stream1 != null) { for (WebRTCPeerConnectionCallback c : callbacks) { c.onStreamRemoved(stream1); } } } @Override public void onRenegotiationNeeded() { for (WebRTCPeerConnectionCallback c : callbacks) { c.onRenegotiationNeeded(); } } }); } @Override public void addCallback(@NotNull WebRTCPeerConnectionCallback callback) { if (!callbacks.contains(callback)) { callbacks.add(callback); } } @Override public void removeCallback(@NotNull WebRTCPeerConnectionCallback callback) { callbacks.remove(callback); } @Override public void addCandidate(int label, @NotNull String id, @NotNull String candidate) { peerConnection.addIceCandidate(label, candidate); } @Override public void addOwnStream(@NotNull CountedReference<WebRTCMediaStream> stream) { peerConnection.addStream(((MediaStream) stream.get()).getStream()); } @Override public void removeOwnStream(@NotNull CountedReference<WebRTCMediaStream> stream) { peerConnection.removeStream(((MediaStream) stream.get()).getStream()); } @NotNull @Override public Promise<WebRTCSessionDescription> setLocalDescription(@NotNull final WebRTCSessionDescription description) { return new Promise<>(new PromiseFunc<WebRTCSessionDescription>() { @Override public void exec(@NotNull final PromiseResolver<WebRTCSessionDescription> resolver) { peerConnection.setLocalDescription(JsSessionDescription.create(description.getType(), description.getSdp()), () -> { resolver.result(description); }, error -> resolver.error(new JavaScriptException(error))); } } ); } @NotNull @Override public Promise<WebRTCSessionDescription> setRemoteDescription(@NotNull final WebRTCSessionDescription description) { return new Promise<>(new PromiseFunc<WebRTCSessionDescription>() { @Override public void exec(@NotNull final PromiseResolver<WebRTCSessionDescription> resolver) { peerConnection.setRemoteDescription(JsSessionDescription.create(description.getType(), description.getSdp()), new JsClosure() { @Override public void callback() { resolver.result(description); } }, new JsClosureError() { @Override public void onError(JavaScriptObject error) { resolver.error(new JavaScriptException(error)); } }); } }); } @NotNull @Override public Promise<WebRTCSessionDescription> createOffer() { return new Promise<>(new PromiseFunc<WebRTCSessionDescription>() { @Override public void exec(@NotNull final PromiseResolver<WebRTCSessionDescription> resolver) { peerConnection.createOffer(new JsSessionDescriptionCallback() { @Override public void onOfferCreated(JsSessionDescription offer) { resolver.result(new WebRTCSessionDescription(offer.getType(), offer.getSDP())); } @Override public void onOfferFailure() { resolver.error(new RuntimeException()); } }); } }); } @NotNull @Override public Promise<WebRTCSessionDescription> createAnswer() { return new Promise<>(new PromiseFunc<WebRTCSessionDescription>() { @Override public void exec(@NotNull final PromiseResolver<WebRTCSessionDescription> resolver) { peerConnection.createAnswer(new JsSessionDescriptionCallback() { @Override public void onOfferCreated(JsSessionDescription offer) { resolver.result(new WebRTCSessionDescription(offer.getType(), offer.getSDP())); } @Override public void onOfferFailure() { resolver.error(new RuntimeException()); } }); } }); } @Override public void close() { if (peerConnection != null) { peerConnection.close(); peerConnection = null; } for (MediaStream s : streams.values()) { s.close(); } streams.clear(); } }